﻿using System;
using System.Linq;
using CardPlay.Model.CardModel;
using CardPlay.Model.GameModel;
using CardPlay.Model.GameModel.Actions;
using CardPlay.Model.GameModel.Presentation;
using CardPlay.Model.Layout;

namespace CardPlay.DemoPack.Games.KlondikeVariants
{
    [Game("2D92EA40-6B34-4D66-9F5F-E6FEE446C30A", LevelOfDifficulty.Easy, LevelOfSkill.ModerateSkill, DurationOfPlay.Within5To10Minutes, Family = FamilyName)]
    public class Klondike : StandardCardGame
    {
        public const string FamilyName = "Klondike";

        public Klondike()
        {
            CardsPerDeal = 1;
            TotalTableaus = 7;
            TableauBuildSequence = CardFaceSequence.AlternatingColorDescendingRank;
            FoundationRowAlignment = HorizontalAlignment.Left;
        }

        public HorizontalAlignment FoundationRowAlignment
        {
            get; set;
        }

        public override ILayoutSite CreatePresentation(IPresentationContext presentation)
        {
            var root = presentation.CreateGridLayout(1, 2);

            {
                var cell = new SideBySideLayout
                {
                    MinimumSpacing = 10,
                    MaximumSpacing = presentation.Metrics.CardSize.Width * 3,
                    Margin = new MarginSize(0, 0, 0, presentation.Metrics.MaxSpacingDown),
                    HorizontalContentAlignment = FoundationRowAlignment
                };
                root.Add(cell);

                var stockWaste = presentation.CreateRowLayout();

                if (PilesNamed(Stock).Any())
                    stockWaste.Add(presentation.CreatePileVisual(Stock, presentation.StyleForStock(this)));

                if (PilesNamed(Waste).Any())
                    stockWaste.Add(presentation.CreatePileVisual(Waste, presentation.StyleForWaste()));

                if (stockWaste.Children.Any())
                    cell.Add(stockWaste);

                var foundations = presentation.CreateRowLayout();
                cell.Add(foundations);

                foundations.HorizontalContentAlignment = HorizontalAlignment.Right;
                presentation.AddPiles(foundations, NamesOfFoundations, presentation.StyleForRepeatedRankFoundation(this, FoundationBaseRank, TotalDecks));

                //presentation.AddFoundationPiles(this, foundations, FoundationBaseRank);
            }

            {
                var cell = CreateTableauPresentation(presentation);
                root.Add(cell);
            }

            return root;
        }

        protected virtual ILayoutSite CreateTableauPresentation(IPresentationContext presentation)
        {
            var tableau = presentation.CreateRowLayout();
            tableau.HorizontalContentAlignment = HorizontalAlignment.Right;

            return presentation.AddTableauPiles(this, tableau);
        }

        protected override void PrepareDealScript(DealScript script)
        {
            DealToTableau(script);
            script.DealRemainingFaceDownTo(Stock);
        }

        protected void DealToTableau(DealScript script, CardOrientation buriedOrientation = CardOrientation.FaceDown)
        {
            var buriedExpression = buriedOrientation == CardOrientation.FaceDown ? "down;" : "up;";

            for (var i = 1; i <= TotalTableaus; ++i)
                script.Deal(String.Concat(Enumerable.Repeat(buriedExpression, i - 1)) + "up").To(StandardPileNames.PrefixForTableau + i);
        }

        protected override bool AllowedToPickupAtTableau(RemovePileAction action)
        {
            return action.IsActingOnFaceUpTopPileInSequence(TableauBuildSequence);
        }

        protected override bool AllowedToBuildEmptyTableau(MovePileAction action)
        {
            return action.PileBeingMoved.BottomCard.Rank == Rank.King;
        }

        protected override void OnTransactionEnding()
        {
            this.FlipFaceDownTopCardsInPilesMatching(AnyTableau);
        }
    }
}
